<template>
  <div v-loading.body.fullscreen.lock="loading" :element-loading-text="loadingText" ref="containerRef"
    class="container"></div>
  <DescDialog ref="descDialogRef" :activeIcon="active">
    <template v-if="active.id == '3'">
      <div class="desc">
        <div class="text">位置：沪聂线安汉路中段右侧</div>
        <div class="text">电话：0836 562 2327</div>
      </div>
    </template>
    <template v-if="active.id == '4'">
      <div class="desc">
        <img class="img" src="/道路图片/江边饭店.jpg" alt="" />
        <div class="text">
          竹巴龙金沙江边的饭店是318国道上最具特色的高原风味驿站，坐落于四川巴塘县与西藏芒康县交界处的金沙江畔。这家饭店以其独特的地理位置和地道的藏式风味，成为往来318国道游客必打卡的美食地标。饭店精选当地高原牧场放养的牦牛肉、藏香猪肉等优质食材，以及山林间采摘的新鲜松茸、羊肚菌等野生菌菇，为食客提供最纯正的高原美味。招牌菜包括豪迈的手抓牦牛肉、风味独特的藏式血肠、浓郁鲜香的酥油炖山菌，以及具有藏族特色的高原土豆糌粑羹。饭店还创新性地将川菜烹饪技法融入传统藏餐，推出改良版的川藏融合菜品，满足不同游客的口味需求。餐厅临江而建，食客可以一边品尝美食，一边欣赏金沙江奔腾的壮丽景色，感受"舌尖上的318"独特魅力。这里不仅是补充能量的驿站，更是体验藏地饮食文化的绝佳场所，为川藏线自驾之旅增添难忘。
        </div>
      </div>
    </template>
    <template v-if="active.id == '2'">
      <div class="desc">
        <img class="img" src="/道路图片/金沙江饭店.jpg" alt="" />
        <div class="text">
          矗立于金沙江奔腾的怒涛之畔，这家江边饭店将藏族文化精髓与高原美食完美融合。餐厅建筑采用传统藏式石木结构，外墙装饰着五彩经幡，入口处悬挂大幅手工唐卡，内部梁柱雕刻着八吉祥图案，营造出浓郁的藏地风情。这里主打"从牧场到餐桌"的高原生态美食：选用金沙江特有的高山冷水裸鲤，以藏式秘制香料腌制后炭火慢烤；散养藏鸡肉质紧实，可烹制藏香鸡火锅或石板煎烤；季节限定的松茸刺身、羊肚菌炖藏鸡更是难得的美味。特别推荐店家自酿的牦牛酸奶，搭配野生蜂蜜和青稞粉，酸甜醇厚。餐厅特设观景露台，食客可一边品尝手抓牦牛肉、酥油茶等地道藏餐，一边欣赏金沙江峡谷的壮美风光，夜幕降临时，篝火晚会与锅庄舞更将藏家热情展现得淋漓尽致。这里不仅是318国道上最具特色的美食驿站，更是一座活态的藏族饮食文化博物馆。
        </div>
      </div>
    </template>
    <template v-if="active.id == '1'">
      <div class="desc">
        <img class="img" src="/道路图片/金沙江大桥.png" alt="" />
        <div class="text">
          竹巴龙金沙江大桥是连接四川甘孜州巴塘县和西藏昌都芒康县的重要通道，是国道318线上出川进藏的关键要塞。
        </div>
        <div class="text">
          据悉，该桥全长361.54米，共15孔，桥墩均采用圆形双柱式墩，双向两车道，时速40km/h，桥面全宽11.5—19.1米。
        </div>
        <div class="text">
          2018年11月，原金沙江大桥被白格堰塞湖泄洪冲毁，2020年5月甘孜交投集团开始新桥建设，倒排工期、挂图作战，提前14个月完成大桥施工任务。
        </div>
      </div>
    </template>
    <template v-if="active.id == '5'">
      <div class="desc">
        <div class="text">名称：茶店民主村4组滑坡</div>
        <div class="text">地址：茶店民主村4组</div>
        <div class="text">经纬度：104.3625N, 30.53333333E</div>
      </div>
    </template>
    <template v-if="active.id == '6'">
      <div class="desc">
        <div class="text">名称：茶店民主村4组滑坡</div>
        <div class="text">地址：茶店民主村4组</div>
        <div class="text">经纬度：104.3625N, 30.53333333E</div>
      </div>
    </template>
    <template v-if="active.id == '7'">
      <div class="desc">
        <div class="text">名称：茶店民主村4组滑坡</div>
        <div class="text">地址：茶店民主村4组</div>
        <div class="text">经纬度：104.3625N, 30.53333333E</div>
      </div>
    </template>
  </DescDialog>
  <VideoDialog :active="active" ref="videoDialogRef" />
</template>

<script setup>
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/addons/renderers/CSS2DRenderer.js";
import {
  CSS3DRenderer,
  CSS3DObject,
} from "three/addons/renderers/CSS3DRenderer.js";

import gsap from "gsap";
import { GUI } from "dat.gui";

import 车道指示器 from "@/assets/imgs/map/车道指示器.png";
import 摄像头 from "@/assets/imgs/map/摄像头.png";
import 消防设备 from "@/assets/imgs/map/消防设备.png";

import 大巴车 from "@/assets/imgs/map/大巴车.png";
import 货车 from "@/assets/imgs/map/货车.png";
import 汽车 from "@/assets/imgs/map/汽车.png";

import 大桥 from "@/assets/imgs/大桥.png";
import 派出所 from "@/assets/imgs/派出所.png";
import 饮食 from "@/assets/imgs/饮食.png";
import 住宿 from "@/assets/imgs/住宿.png";
import 崩塌 from "/灾害点/崩塌.png";
import 滑坡 from "/灾害点/滑坡.png";
import 泥石流 from "/灾害点/泥石流.png";

import 道路 from "@/assets/imgs/道路.png";

import 出现紧急情况1 from "@/assets/imgs/map/出现紧急情况 (1).png";

import VideoDialog from "./common/videoControlDialog/index.vue";
import DescDialog from "./common/descDialog/index.vue";
import { useTemplateRef } from "vue";
import {
  generateFluctuatingAltitude,
  generateRandomLicensePlate,
} from "@/utils/index.js";

const isDark = useDark();

const containerRef = useTemplateRef("containerRef");
const loading = ref(false);
const loadingText = ref("加载中...");

const currentWaterDate = ref({});
const waterPopupRef = ref(null);
const descDialogRef = useTemplateRef("descDialogRef");
const videoDialogRef = useTemplateRef("videoDialogRef");

let renderer,
  scene,
  camera,
  controls,
  gui,
  loader,
  css2Renderer,
  css3Renderer,
  globalTime,
  masterModel,
  draco,
  clock,
  animationFrameId,
  directionalLight,
  ambientLight;
const iconDatas = ref([
  {
    name: "监控", // 用于查找
    label: "频道1", // 用于显示
    img: 摄像头,
    id: 1,
    src: "/然乌镇视频/1.mp4",
  },
  {
    name: "监控001",
    label: "频道2", // 用于显示
    img: 摄像头,
    id: 2,
    src: "/然乌镇视频/2.mp4",
  },
  {
    name: "监控002",
    label: "频道3", // 用于显示
    img: 摄像头,
    id: 3,
    src: "/然乌镇视频/3.mp4",
  },
  // {
  //     name: '右上消防',
  //     img: 消防设备,
  //     id: 3
  // },
  // {
  //     name: '左上消防',
  //     img: 消防设备,
  //     id: 3
  // },
  // {
  //     name: '左下消防',
  //     img: 消防设备,
  //     id: 3
  // },
  // {
  //     name: '芒康路牌',
  //     img: 车道指示器,
  //     id: 1
  // },
  // {
  //     name: '桥头路牌',
  //     img: 车道指示器,
  //     id: 1
  // }
]);
const cardDatas = [
  {
    name: "大巴01.001",
    url: "/车辆动画/大巴01.001.gltf",
    img: 大巴车,
    data: {
      number: generateRandomLicensePlate(),
      type: "大巴车",
      speed: 60,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
    // url: '/货车关键帧.gltf',
  },
  {
    name: "大巴01.002",
    url: "/车辆动画/大巴01.002.gltf",
    img: 大巴车,
    data: {
      number: generateRandomLicensePlate(),
      type: "大巴车",
      speed: 60,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  /* {
          name: '大巴01',
          url: '/车辆动画/大巴01.gltf',
          img: 大巴车
      }, */
  {
    name: "大巴02.001",
    url: "/车辆动画/大巴02.001.gltf",
    img: 大巴车,
    data: {
      number: generateRandomLicensePlate(),
      type: "大巴车",
      speed: 67,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  // {
  //     name: '大巴02.002',
  //     position: '/车辆动画/大巴02.002.gltf',
  // },
  /*   {
            name: '大巴02',
            url: '/车辆动画/大巴02.gltf',
            img: 大巴车
        }, */
  {
    name: "货车01.001",
    url: "/车辆动画/货车01.001.gltf",
    img: 货车,
    data: {
      number: generateRandomLicensePlate(),
      type: "货车",
      speed: 66,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  {
    name: "货车01.002",
    url: "/车辆动画/货车01.002.gltf",
    img: 货车,
    data: {
      number: generateRandomLicensePlate(),
      type: "货车",
      speed: 70,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  /*   {
            name: '货车01',
            url: '/车辆动画/货车01.gltf',
            img: 货车
        }, */
  {
    name: "货车02.001",
    url: "/车辆动画/货车02.001.gltf",
    img: 货车,
    data: {
      number: generateRandomLicensePlate(),
      type: "货车",
      speed: 58,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  {
    name: "货车02.002反向",
    url: "/车辆动画/货车02.002反向.gltf",
    img: 货车,
    data: {
      number: generateRandomLicensePlate(),
      type: "货车",
      speed: 50,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  /* {
          name: '货车02',
          url: '/车辆动画/货车02.gltf',
          img: 货车
      }, */
  // {
  //     name: '桥车01.001',
  //     url: '/车辆动画/桥车01.001.gltf',
  // },
  // {
  //     name: '桥车01.002反向',
  //     url: '/车辆动画/桥车01.002反向.gltf',
  // },
  // {
  //     name: '桥车01',
  //     url: '/车辆动画/桥车01.gltf',
  // },
  {
    name: "皮卡01.001",
    url: "/车辆动画/皮卡01.001.gltf",
    img: 汽车,
    data: {
      number: generateRandomLicensePlate(),
      type: "汽车",
      speed: 60,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  {
    name: "皮卡01.002",
    url: "/车辆动画/皮卡01.002.gltf",
    img: 汽车,
    data: {
      number: generateRandomLicensePlate(),
      type: "汽车",
      speed: 66,
      altitude: generateFluctuatingAltitude(2400, 100),
    },
  },
  /*  {
           name: '皮卡01',
           url: '/车辆动画/皮卡01.gltf',
           img: 汽车
       }, */
];
const waterIconDatas = [
  {
    id: "freeze",
    name: "路面结冰",
    options: {
      offset: [-40, -27, 0],
      rotation: [0, Math.PI / 2, 0],
    },
  },
  {
    id: "water",
    name: "路面积水",
    options: {
      offset: [-42, -28, -80],
      rotation: [0, 0, 0],
    },
  },
  {
    id: "rockfall",
    name: "落石",
    options: {
      offset: [62, -28, -80],
      rotation: [0, Math.PI, 0],
    },
  },
];

const introduceIconDatas = [
  {
    id: 1,
    name: "金沙江大桥",
    img: 大桥,
    des: "金沙江大桥位于中国四川省成都市青羊区，是一座跨过金沙江的桥梁，连接着成都市青羊区与成都市锦江区。这座桥梁全长约1.3公里，宽约30米，是成都市区内最长的桥梁之一。金沙江大桥是一座重要的交通枢纽，每天有大量的车辆和行人通过。",
  },
  {
    id: 2,
    name: "金沙江饭店",
    img: 饮食,
    des: "金沙江饭店位于中国四川省成都市锦江区，是一座位于成都锦江区的餐饮酒店。该酒店位于成都锦江区的一个重要交通枢纽，是成都锦江区的一个重要餐饮目的地。",
  },
  {
    id: 3,
    name: "竹巴笼派出所",
    img: 派出所,
    des: "竹巴笼派出所是成都锦江区的一个重要的治安管理机构，也是成都锦江区的一个重要的旅游目的地。该派出所的地址是四川省成都市锦江区竹巴笼镇，是成都锦江区的一个重要的治安管理机构，也是成都锦江区的一个重要的旅游目的地。",
  },
  {
    id: 4,
    name: "江边饭馆",
    img: 饮食,
    des: "江边饭馆位于中国四川省成都市锦江区，是一家位于成都锦江区的一个餐饮酒店。该酒店位于成都锦江区的一个重要交通枢纽，是成都锦江区的一个重要餐饮目的地。",
  },
];
const active = ref({}); // 当前激活的图标
const hasMoved = ref(false); // 是否移动过摄像头
const disasterPoints = [
  {
    id: 5,
    name: "崩塌",
    img: 崩塌,
    position: { x: 100, y: -20, z: -100 },
  },
  {
    id: 6,
    name: "滑坡",
    position: { x: -65, y: -20, z: 0 },
    img: 滑坡,
  },
  {
    id: 7,
    name: "泥石流",
    img: 泥石流,
    position: { x: 55, y: -20, z: 20 },
  },
];
const initLight = () => {
  console.log("isDark", isDark.value, scene);
  if (ambientLight) scene.remove(ambientLight);
  if (directionalLight) scene.remove(directionalLight);
  if (isDark.value) {
    // 暗黑模式
    // scene.background = new THREE.Color(0x000000);
    scene.fog = new THREE.Fog(0x000000, 50, 1000); // Near设为50，避免近处物体完全被雾覆盖
    // if (ambientLight) scene.remove(ambientLight);
    // if (directionalLight) scene.remove(directionalLight);

    scene.background = new THREE.Color(0x000000); // 黑色
    ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambientLight);
  } else {
    // 正常模式
    scene.background = new THREE.Color(0x87ceeb); // 天空蓝色
    ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    scene.add(ambientLight);
    directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(5, 10, 5); // 提高光源高度以生成自然投影
    directionalLight.castShadow = true; // 启用阴影投射
    directionalLight.shadow.camera.top = 20;
    directionalLight.shadow.camera.bottom = -20;
    directionalLight.shadow.camera.left = -20;
    directionalLight.shadow.camera.right = 20;
    scene.add(directionalLight);
    scene.fog = null;
  }
  if (renderer) {
    renderer.shadowMap.enabled = true; // 启用阴影贴图
    renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 使用软阴影优化边缘质量
  }
};

watch(
  () => isDark.value,
  () => {
    if (scene) {
      initLight();
    }
  }
);
// watchEffect(() => {
//     if (scene) {
//         initLight()
//     }
// });

const activeEquipment = ref("全部");
/** 点击视角 */
const watchAngle = () => {
  window.addEventListener("changeAngle", (e) => {
    console.log("www", e.detail);
    const { angle, back } = e.detail;
    if (timer) clearTimeout(timer);
    hasMoved.value = false;
    moveCamera(angle, masterModel.position);
    clearCarLabel();
    clearCarLoop();
    clearLoadRoadLabel();
  });
};
/** 点击设备 */
// const watchCustomEvent = () => {
//   window.addEventListener('changeEquipment', (e) => {
//     const { name, id } = e.detail
//     clearRoad()
//     activeEquipment.value = name
//     const data = id === 4 ? roadData.value : roadData.value.filter((i) => i.id === id)
//     data.forEach((item) => {
//       const obj = masterModel.children.find((child) => child.name === item.name)
//       if (!obj || !obj.children.length) return
//       obj.children[obj.children.length - 1].visible = true
//     })
//   })
// }
/** 点击紧急情况表格 */
const watchHistoryEvent = () => {
  window.addEventListener("clickWateHanle", (e) => {
    console.log("row", e.detail);
    const { row } = e.detail;
    console.log("row", row);

    const doms = document.querySelector("." + row.type);
    console.log("doms", doms);
    if (!doms) {
      active.value = row;
      descDialogRef.value.open();
      return;
    }
    // 获取图片
    doms.querySelector(".img").style.display = "block";
    setTimeout(() => {
      doms.querySelector(".img").style.display = "none";
    }, 10000);

    // const index = Math.floor(Math.random() * doms.length)
    // const dom = doms[index];// 随机获取一个dom
    // const item = waterIconDatas[index];// 随机获取一个item
    // console.log("item", dom, item);
    // dom.addEventListener('click', (e) => {
    //     e.stopPropagation();
    //     const model = scene.children.find(v => v.name === item.name)
    //     clickWater(item, model);
    // })

    // dom.click()
  });
};

/** 加载积水模型  */
const loadWater = () => {
  waterIconDatas.forEach((item) => {
    loader.load(`/${item.name}.gltf`, (gltf) => {
      console.log("gltf", gltf);

      const model = gltf.scene;
      model.position.set(
        item.options.offset[0],
        item.options.offset[1],
        item.options.offset[2]
      );
      model.rotation.set(
        item.options.rotation[0],
        item.options.rotation[1],
        item.options.rotation[2]
      );
      model.name = item.name;
      scene.add(model);
      const dom = document.createElement("div");
      dom.className = item.id;
      dom.innerHTML = `
                    <img class="img" src="${出现紧急情况1}" alt="">
                    <span class="text">${item.name}</span>
                `;
      // 添加点击事件
      // dom.addEventListener('click', (e) => {
      // e.stopPropagation();
      // clickWater(item, model);
      // });
      const tag = new CSS2DObject(dom);
      tag.position.z += 4; // 标签高度偏移量
      labelElements.push({ dom: dom, object3D: tag });
      model.add(tag); // 标签跟随父对象移动
    });
  });
};
/** 点击积水 */
const clickWater = (item, model) => {
  nextTick(() => {
    currentWaterDate.value = item;
    const modelWorldPos = new THREE.Vector3();
    model.getWorldPosition(modelWorldPos);
    const cameraOffset = new THREE.Vector3(
      50 + 10, // X轴动态偏移量
      20 + 10, // Y轴固定高度
      40 + 10 // Z轴基础距离
    );
    const cameraTargetPos = modelWorldPos.clone().add(cameraOffset);
    moveCamera(cameraTargetPos, modelWorldPos, () => {
      setTimeout(() => {
        waterPopupRef.value.open();
      }, 500);
    });
  });
};
/** 隐藏积水 */
const clearWater = () => {
  const modelName = waterIconDatas.map((i) => i.name);
  scene.children.forEach((child) => {
    if (modelName.includes(child.name)) {
      child.visible = false;
    }
  });
};

// const loadRoad1 = () => {
//   if (!masterModel) return;
//   roadData.forEach((item) => {
//     const model = masterModel.children.find((v) => v.name === item.name);
//     if (!model) return;
//     const dom = document.createElement("div");
//     dom.className = "road";
//     dom.innerHTML = `
//             <img class="img" src="${item.img}" alt="">
//         `;
//     let domWidth = 0;
//     dom.addEventListener("click", (e) => {
//       e.stopPropagation();
//       clearCarLabel();
//       clearCarLoop();
//       window.dispatchEvent(
//         new CustomEvent("footerClick", { detail: { type: "other" } })
//       );
//       domWidth += 1;
//       if (domWidth == 2) {
//         videoDialogRef.value.open();
//         domWidth = 0;
//       }
//       const modelWorldPos = new THREE.Vector3();
//       model.getWorldPosition(modelWorldPos);
//       const cameraOffset = new THREE.Vector3(
//         Math.sin(Date.now() * 0.002) * 5, // X轴动态偏移量
//         20, // Y轴固定高度
//         40 // Z轴基础距离
//       );
//       const cameraTargetPos = modelWorldPos.clone().add(cameraOffset);
//       moveCamera(cameraTargetPos, modelWorldPos);
//     });
//     const tag = new CSS2DObject(dom);
//     labelElements.push({ dom: dom, object3D: tag });
//     model.add(tag);
//   });
// };

/** 加载道路上的图标 */
const loadRoad = () => {
  if (!masterModel) return;
  iconDatas.value.forEach((item) => {
    const model = masterModel.children.find(
      (child) => child.name === item.name
    );
    if (!model) return;
    const dom = document.createElement("div");
    dom.className = "road";
    dom.style.pointerEvents = "auto"; // 确保点击事件能触发
    dom.innerHTML = `
     <div class="text textDom">点击查看</div>
    <img class="img" src="${item.img}" alt="">
    `;
    let isShow = false;
    const img = dom.querySelector(".img");
    const text = dom.querySelector(".text");

    img.addEventListener("click", (e) => {
      e.stopPropagation();
      clearCarLabel();
      clearCarLoop();
      clearLoadRoadLabel();
      text.style.opacity = isShow ? 0 : 1;
      window.dispatchEvent(
        new CustomEvent("footerClick", { detail: { type: "other" } })
      );
      const modelWorldPos = new THREE.Vector3();
      model.getWorldPosition(modelWorldPos);
      const cameraOffset = new THREE.Vector3(
        Math.sin(Date.now() * 0.002) * 5, // X轴动态偏移量
        20, // Y轴固定高度
        40 // Z轴基础距离
      );
      const cameraTargetPos = modelWorldPos.clone().add(cameraOffset);
      if (active.value.name !== item.name) {
        active.value = item;
        hasMoved.value = false;
        moveCamera(cameraTargetPos, modelWorldPos);
        hasMoved.value = true;
      } else {
        if (hasMoved.value) {
          videoDialogRef.value.open(text);
          hasMoved.value = false; // 重置状态
        } else {
          videoDialogRef.value.open(text);
          moveCamera(cameraTargetPos, modelWorldPos);
          hasMoved.value = true;
        }
      }
    });
    const tag = new CSS2DObject(dom);
    labelElements.push({ dom: dom, object3D: tag });
    model.add(tag);
  });
};

const clearLoadRoadLabel = () => {
  const textDoms = document.querySelectorAll(".textDom");
  textDoms?.forEach((item) => {
    item.style.opacity = 0;
  });
};

/** 隐藏道路上的图标 */
const clearRoad = () => {
  if (!masterModel) return;
  iconDatas.value.forEach((item) => {
    const obj = masterModel.children.find((child) => child.name === item.name);
    if (!obj || !obj.children.length) return;
    obj.children[obj.children.length - 1].visible = false;
  });
};
const carMap = new Map();
const mixers = []; // 全局存储所有动画混合器
/** 加载汽车模型 */
const loadCar = () => {
  cardDatas.forEach((item) => {
    loader.load(item.url, (gltf) => {
      const model = gltf.scene;
      console.log("gltf", gltf);

      // model.name = item.name;
      scene.add(model);
      // 创建CSS2D标签
      const dom = document.createElement("div");
      dom.className = "card";
      dom.innerHTML = `
                <img class="img" src="${item.img}" alt="">
            `;
      const label = new CSS2DObject(dom);
      label.position.set(0, 10, 0);
      label.name = "label";
      label.visible = true;
      model.children[0].add(label);
      labelElements.push({ dom: dom, object3D: label });
      const dom2 = document.createElement("div");
      dom2.className = "cardPopup";
      dom2.innerHTML = `
           <div class="header">
      <div class="title">车辆信息</div>
        <img src="/prefix/close.png" class="close" alt="">
           </div>
            <div class="content1">
              <div class="item">
                <span>车牌号：</span>
                <span>${item.data.number}</span>
             </div> 
              <div class="item">
                <span>车辆类型：</span>
                <span>${item.data.type}</span>
             </div>
              <div class="item">
                <span>行驶速度：</span>
                <span class="speed">${item.data.speed}km/h</span> 
             </div>
              <div class="item">
                <span>海拔高度：</span>
                <span>${item.data.altitude}M</span>
             </div>
            </div>
            `;
      const label2 = new CSS2DObject(dom2);
      label2.position.set(0, 2, 0);
      label2.name = "popup";
      label2.visible = false;
      model.children[0].add(label2);
      // 创建动画混合器
      const mixer = new THREE.AnimationMixer(model);
      mixer.speed = 0.1;
      mixers.push(mixer);
      // 播放动画
      const action = mixer.clipAction(gltf.animations[0]);
      action.timeScale = 0.5; // 2倍速播放
      action.play();

      // 添加点击事件
      dom.addEventListener("click", (e) => {
        e.stopPropagation();
        clearLoadRoadLabel();
        clearCarLabel();
        closeCardPopup();
        carMap.set(model, {
          initialSpeed: Number(item.data.speed) || 60, // 强制转换为数值
          speedElement: dom2.querySelector(".speed"),
          mixer: mixer,
          currentFactor: 1, // 当前速度因子
          targetFactor: 3, // 目标速度因子
          acceleration: 0.003,
          isMaxSpeed: false,
        });
        clickCar(item, model);
      });
      // 关闭按钮
      dom2.querySelector('.close').addEventListener('click', (e) => {
        e.stopPropagation()
        move()
      })
    });
  });
};
/** 显示汽车模型标签 */
const showCarLabel = () => {
  scene.traverse((child) => {
    cardDatas.forEach((item) => {
      if (child.name == "label") {
        child.visible = true;
      }
      if (child.name == "popup") {
        child.visible = false;
      }
    });
  });
};
/** 隐藏汽车模型标签 */
const clearCarLabel = () => {
  if (timer) clearTimeout(timer);
  scene.traverse((child) => {
    // if (child.name == 'label') {
    //     child.visible = false
    // }
    if (child.name == "popup") {
      child.visible = false;
    }
  });
};
let followTarget = null; // 跟踪的目标
const cameraOffset = new THREE.Vector3(10, 5, 0);
const lerpAlpha = 0.06; // 阻尼系数，范围 0–1
/** 点击汽车标签 */
const clickCar = (item, model) => {
  window.dispatchEvent(
    new CustomEvent("footerClick", { detail: { type: "other" } })
  );
  // 清除之前的标签（popup）
  scene.traverse((child) => {
    if (child.name == "popup") child.visible = false;
  });
  model.children[0].children.find((i) => i.name == "popup").visible = true;
  model.children[0].children.find((i) => i.name == "label").visible = false;
  followTarget = model.children[0];

  const worldPos = new THREE.Vector3();
  const worldQuat = new THREE.Quaternion();
  followTarget.getWorldPosition(worldPos);
  followTarget.getWorldQuaternion(worldQuat);
  // 2. 偏移向量按模型朝向旋转
  const localOffset = cameraOffset.clone().applyQuaternion(worldQuat);
  // 3. 目标相机位置
  const desiredPos = worldPos.clone().add(localOffset);
  // 4. 平滑过渡
  // camera.position.lerp(desiredPos, lerpAlpha);
  controls.target.lerp(worldPos, lerpAlpha);

  moveCamera(masterModel.position, followTarget.position);
  // carloop();
};

const clearCarLoop = () => {
  followTarget = null;
};
const loadIcon = () => {
  if (!masterModel) return;
  const children = masterModel.children;
  introduceIconDatas.forEach((item) => {
    const dom = document.createElement("div");
    dom.className = "introduce";
    dom.innerHTML = `
      <div class="text">${item.name}</div>
      <img class="img" src="${item.img}" alt="">
    `;
    let isShow = false;
    const img = dom.querySelector(".img");
    const text = dom.querySelector(".text");
    const obj = children.find((v) => v.name === item.name);
    if (!obj) return;
    // let domWidth = 0;
    img.addEventListener("click", (e) => {
      e.stopPropagation();
      clearCarLabel();
      clearCarLoop();
      closeCardPopup();
      clearLoadRoadLabel();
      text.style.opacity = isShow ? "0" : "1";
      active.value = item;
      // domWidth += 1
      // if (domWidth == 2) {
      descDialogRef.value.open(text);
      //     domWidth = 0
      // }

      const modelWorldPos = new THREE.Vector3();
      obj.getWorldPosition(modelWorldPos);
      const cameraOffset = new THREE.Vector3(
        Math.sin(Date.now() * 0.002) * 5, // X轴动态偏移量
        20, // Y轴固定高度
        40 // Z轴基础距离
      );
      const cameraTargetPos = modelWorldPos.clone().add(cameraOffset);
      // moveCamera(cameraTargetPos, modelWorldPos);
    });
    const tag = new CSS2DObject(dom);
    obj.updateMatrixWorld();
    const worldPos = new THREE.Vector3();
    obj.getWorldPosition(worldPos);

    // 补偿高度差（根据实际图标尺寸调整）
    worldPos.y += 0; // 假设图标高度30px，补偿15px
    tag.position.copy(worldPos);
    labelElements.push({ dom: dom, object3D: tag });
    scene.add(tag); // 添加到场景而非obj
  });
};

const loadDisasterPoints = () => {
  disasterPoints.forEach((item) => {
    if (!masterModel) return;
    // 创建dom 并设置位置 添加到场景中
    const dom = document.createElement("div");
    dom.className = "disasterPoints";
    dom.innerHTML = `
       <div class="text">${item.name}</div>
       <img class="img" src="${item.img}" alt="">
     `;
    const tag = new CSS2DObject(dom);
    tag.position.set(item.position.x, item.position.y, item.position.z);
    labelElements.push({ dom: dom, object3D: tag });
    // scene.add(tag);
    masterModel.add(tag); // 添加到场景而非obj
    let isShow = false;
    const img = dom.querySelector(".img");
    const text = dom.querySelector(".text");
    img.addEventListener("click", (e) => {
      e.stopPropagation();
      clearCarLabel();
      clearCarLoop();
      closeCardPopup();
      clearLoadRoadLabel();
      text.style.opacity = isShow ? "0" : "1";
      active.value = item;
      descDialogRef.value.open(text);
      // }S
      const modelWorldPos = new THREE.Vector3();
      obj.getWorldPosition(modelWorldPos);
      const cameraOffset = new THREE.Vector3(
        Math.sin(Date.now() * 0.002) * 5, // X轴动态偏移量
        20, // Y轴固定高度
        40 // Z轴基础距离
      );
      const cameraTargetPos = modelWorldPos.clone().add(cameraOffset);
      // moveCamera(cameraTargetPos, modelWorldPos);
    });
  });
};
/** 加载主体模型 */
const loadModel = () => {
  loading.value = true;
  loader.load(
    "/整体.gltf",
    (gltf) => {
      loading.value = false;
      const model = gltf.scene;
      masterModel = model;
      scene.add(masterModel);
      camera.position.set(-100, 0, 100);
      // camera.lookAt(masterModel.position);
      // controlShow()
      console.log("加载完成", model);
      loadWater();
      loadCar();
      loadIcon();
      loadRoad();
      loadDisasterPoints();
    },
    (progress) => {
      const s = progress.loaded / progress.total;
      console.log("加载进度:", s);
      loadingText.value = `加载进度: ${Math.floor(s * 100)}%`;
    },
    (error) => {
      console.error("GLB加载失败:", error);
    }
  );
};

/** 移动相机 */
const moveCamera = (targetPos, lookAtPos, onComplete) => {
  if (!lookAtPos) return;
  const tl = gsap.timeline({ defaults: { duration: 2, ease: "power2.inOut" } });
  // 位置动画
  tl.to(
    camera.position,
    {
      x: targetPos.x,
      y: targetPos.y,
      z: targetPos.z,
    },
    "start"
  );

  // 目标点动画（同步执行）
  tl.to(
    controls.target,
    {
      x: lookAtPos.x,
      y: lookAtPos.y,
      z: lookAtPos.z,
      onUpdate: () => controls.update(),
    },
    "start"
  );

  // 状态管理
  tl.call(() => {
    controls.enabled = true;
    onComplete?.();
  });
};

const initThree = () => {
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.domElement.style.zIndex = -1;
  containerRef.value.appendChild(renderer.domElement);

  scene = new THREE.Scene();
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  controls = new OrbitControls(camera, renderer.domElement);

  // controls.enableDamping = true;
  // controls.dampingFactor = 0.25;
  controls.enablePan = false; // 启用平移
  // 控制器限制
  controls.minDistance = 50; // 最小距离
  controls.maxDistance = 200; // 最大距离

  controls.minPolarAngle = 0; // 0 = 正上方
  controls.maxPolarAngle = Math.PI / 3; // π/2 = 水平视角

  camera.position.set(0, 0, 0);
  controls.target.set(0, 0, 0);
  controls.update();

  initLight();
  // // 添加天空颜色
  // scene.background = new THREE.Color(0x87CEEB); // 天空蓝色

  // // 添加环境光
  // ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
  // scene.add(ambientLight);

  // // 添加平行光
  // directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  // directionalLight.position.set(5, 5, 5);
  // scene.add(directionalLight);

  // 创建时钟
  clock = new THREE.Clock();

  // 创建gsap时间线
  globalTime = gsap.timeline({ paused: true });
};

// 创建css2渲染器
const initCSS2Renderer = () => {
  css2Renderer = new CSS2DRenderer();
  css2Renderer.setSize(window.innerWidth, window.innerHeight);
  css2Renderer.domElement.style.position = "absolute";
  css2Renderer.domElement.style.top = "0px";
  css2Renderer.domElement.style.pointerEvents = "none";
  css2Renderer.domElement.classList.add("css2");
  containerRef.value.appendChild(css2Renderer.domElement);
  css2Renderer.domElement.style.zIndex = 0;
};
// 创建css3渲染器
const initCSS3Renderer = () => {
  css3Renderer = new CSS3DRenderer();
  css3Renderer.setSize(window.innerWidth, window.innerHeight);
  css3Renderer.domElement.style.position = "absolute";
  css3Renderer.domElement.style.top = "0px";
  css2Renderer.domElement.style.pointerEvents = "none";
  css3Renderer.domElement.classList.add("css3");
  containerRef.value.appendChild(css3Renderer.domElement);
  css3Renderer.domElement.style.zIndex = 0;
};

/** 初始化draco */
const initDraco = () => {
  draco = new DRACOLoader();
  draco.setDecoderPath("/prefix/draco/");
};
/** 初始话loader */
const initLoader = () => {
  loader = new GLTFLoader();
  loader.setDRACOLoader(draco);
};
const labelElements = []; // 存储所有标签DOM

const checkOcclusion = () => {
  const raycaster = new THREE.Raycaster();
  const cameraPosition = camera.position.clone();

  labelElements.forEach(({ dom, object3D }) => {
    // 1. 获取标签的世界坐标（不修改原始值）
    const labelWorldPos = new THREE.Vector3();
    object3D.getWorldPosition(labelWorldPos);

    // 2. 计算射线方向（从相机到标签）
    const rayDirection = labelWorldPos.clone().sub(cameraPosition).normalize();

    // 3. 设置射线（起点稍微靠近相机，避免近裁剪面问题）
    const rayOrigin = cameraPosition
      .clone()
      .add(rayDirection.multiplyScalar(0.1));
    raycaster.set(rayOrigin, rayDirection);

    // 4. 检测遮挡（排除标签自身和透明物体）
    const intersects = raycaster.intersectObjects(scene.children, true);
    const isOccluded = intersects.some((intersect) => {
      return (
        intersect.distance < cameraPosition.distanceTo(labelWorldPos) - 0.1 && // 容差阈值
        !intersect.object.isLabel &&
        !(intersect.object.material && intersect.object.material.transparent)
      );
    });

    // 5. 更新标签可见性
    dom.style.visibility = isOccluded ? "hidden" : "visible";
  });
};

// 添加动画循环
const animate = () => {
  requestAnimationFrame(animate);
  // 更新所有动画混合器
  const delta = clock.getDelta();
  mixers.forEach((mixer) => {
    mixer.getRoot().updateMatrixWorld(true); // 关键：强制更新根节点矩阵
    mixer.update(delta);
  });

  if (followTarget) {
    // 1. 世界空间的位置与旋转
    const worldPos = new THREE.Vector3();
    const worldQuat = new THREE.Quaternion();
    followTarget.getWorldPosition(worldPos);
    followTarget.getWorldQuaternion(worldQuat);
    // 2. 偏移向量按模型朝向旋转
    const localOffset = cameraOffset.clone().applyQuaternion(worldQuat);
    // 3. 目标相机位置
    const desiredPos = worldPos.clone().add(localOffset);
    // 4. 平滑过渡
    // camera.position.lerp(desiredPos, lerpAlpha);
    controls.target.lerp(worldPos, lerpAlpha);
  }
  carMap.forEach((data, model) => {
    if (!data.speedElement || data.isMaxSpeed) return;
    data.currentFactor += data.acceleration * delta;
    if (data.currentFactor >= data.targetFactor) {
      data.currentFactor = data.targetFactor;
      data.isMaxSpeed = true;
    }
    const currentSpeed = data.initialSpeed * data.currentFactor;
    data.speedElement.textContent = `${currentSpeed.toFixed(1)}km/h`;
    if (data.mixer) {
      data.mixer.speed = data.currentFactor * 0.1;
    }
  });

  checkOcclusion();

  // 确保场景矩阵更新
  scene.updateMatrixWorld(true);

  renderer.render(scene, camera);
  controls.update();
  css2Renderer.render(scene, camera);
  // css3Renderer.render(scene, camera);
};

// 添加窗口resize处理
const onWindowResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  css2Renderer.setSize(window.innerWidth, window.innerHeight);
  // css3Renderer.setSize(window.innerWidth, window.innerHeight);
};
/** 创建辅助线 */
const createHelper = (
  position = {
    x: 0,
    y: 0,
    z: 0,
  }
) => {
  const axesHelper = new THREE.AxesHelper(50);
  axesHelper.position.set(position.x, position.y, position.z); // 设置辅助线的位置
  scene.add(axesHelper);
};
// 添加GUI调试
const addDebugGUI = () => {
  gui = new GUI();
  // 相机位置控制
  const cameraFolder = gui.addFolder("相机位置");
  cameraFolder.add(camera.position, "x", -300, 300).name("X轴");
  cameraFolder.add(camera.position, "y", -300, 300).name("Y轴");
  cameraFolder.add(camera.position, "z", -300, 300).name("Z轴");
  cameraFolder.open();

  // 相机旋转控制（弧度）
  // const rotationFolder = gui.addFolder('相机旋转');
  // rotationFolder.add(camera.rotation, 'x', 0, Math.PI * 2).name('X轴');
  // rotationFolder.add(camera.rotation, 'y', 0, Math.PI * 2).name('Y轴');
  // rotationFolder.add(camera.rotation, 'z', 0, Math.PI * 2).name('Z轴');
  // rotationFolder.open();

  // 控制器目标位置（核心修复）
  // const targetFolder = gui.addFolder('控制器目标');
  // targetFolder.add(controls.target, 'x', -200, 200).name('X轴').onChange(() => controls.update());
  // targetFolder.add(controls.target, 'y', -200, 200).name('Y轴').onChange(() => controls.update());
  // targetFolder.add(controls.target, 'z', -200, 200).name('Z轴').onChange(() => controls.update());
  // targetFolder.open();
};
onMounted(() => {
  initThree();
  initCSS2Renderer();
  // initCSS3Renderer();
  initDraco();
  initLoader();
  loadModel();
  // addDebugGUI()
  // createHelper();
  animate();
  window.addEventListener("resize", onWindowResize);
  watchAngle();
  // watchCustomEvent()
  watchHistoryEvent();
});

onUnmounted(() => {
  window.removeEventListener("resize", onWindowResize);
  if (renderer) renderer.dispose();
  if (timer) clearTimeout(timer);
});
// 移动相机
const move = () => {
  if (timer) clearTimeout(timer);
  hasMoved.value = false;
  moveCamera({ x: -100, y: 0, z: 100 }, masterModel.position);
  clearCarLoop();
  clearCarLabel();
  clearLoadRoadLabel();
};
let timer = null;
/** 15sw后自动关闭弹窗 */
const closeCardPopup = () => {
  timer = setTimeout(() => {
    move();
    window.dispatchEvent(
      new CustomEvent("footerClick", { detail: { type: "back" } })
    );
  }, 15000);
};
defineExpose({ move });
</script>

<style scoped lang="scss">
.container {
  width: 100%;
  height: 100%;
}
</style>
